package com.bluesky.system.service.impl;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.util.StrUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.bluesky.common.enums.StatusEnum;
import com.bluesky.common.exception.CustomException;
import com.bluesky.common.util.SecurityUtils;
import com.bluesky.system.common.dto.SysPostAddDTO;
import com.bluesky.system.common.dto.SysPostEditDTO;
import com.bluesky.system.common.dto.SysPostQueryDTO;
import com.bluesky.system.entity.SysPost;
import com.bluesky.system.entity.SysTenant;
import com.bluesky.system.entity.SysUserPost;
import com.bluesky.system.mapper.SysPostMapper;
import com.bluesky.system.service.ISysPostService;
import com.bluesky.system.service.ISysTenantService;
import com.bluesky.system.service.ISysUserPostService;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.Resource;
import java.util.Arrays;
import java.util.List;
import java.util.Objects;

/**
 * <p>
 * 岗位表 服务实现类
 * </p>
 *
 * @author Kevin
 * @since 2021-06-22
 */
@Service
public class SysPostServiceImpl extends ServiceImpl<SysPostMapper, SysPost> implements ISysPostService {

    @Resource
    private ISysTenantService sysTenantService;
    @Resource
    private ISysUserPostService sysUserPostService;

    @Override
    public IPage<SysPost> page(Page reqPage, SysPostQueryDTO req) {
        LambdaQueryWrapper<SysPost> queryWrapper = Wrappers.lambdaQuery();
        queryWrapper.like(StrUtil.isNotBlank(req.getPostCode()), SysPost::getPostCode, req.getPostCode());
        queryWrapper.like(StrUtil.isNotBlank(req.getPostName()), SysPost::getPostName, req.getPostName());
        queryWrapper.eq(SysPost::getTenantId, SecurityUtils.getTenantId());
        queryWrapper.orderByAsc(SysPost::getSort);
        IPage<SysPost> page = this.page(reqPage, queryWrapper);
        page.getRecords().forEach(item -> {
            // 设置租户名称
            SysTenant sysTenant = sysTenantService.getById(item.getTenantId());
            item.setTenantName(Objects.isNull(sysTenant) ? null : sysTenant.getTenantName());
        });
        return page;
    }

    @Override
    public List<SysPost> list(SysPostQueryDTO req) {
        LambdaQueryWrapper<SysPost> queryWrapper = Wrappers.lambdaQuery();
        queryWrapper.like(StrUtil.isNotBlank(req.getPostCode()), SysPost::getPostCode, req.getPostCode());
        queryWrapper.like(StrUtil.isNotBlank(req.getPostName()), SysPost::getPostName, req.getPostName());
        queryWrapper.eq(SysPost::getTenantId, SecurityUtils.getTenantId());
        queryWrapper.orderByAsc(SysPost::getSort);
        return this.list(queryWrapper);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void add(SysPostAddDTO req) {
        if (!this.checkUniquePostName(req.getPostName(), null, req.getTenantId())) {
            throw new CustomException("岗位名称已存在");
        }
        if (!this.checkUniquePostCode(req.getPostCode(), null, req.getTenantId())) {
            throw new CustomException("岗位编码已存在");
        }
        SysPost entity = BeanUtil.copyProperties(req, SysPost.class);
        this.save(entity);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void edit(SysPostEditDTO req) {
        if (!this.checkUniquePostName(req.getPostName(), req.getId(), req.getTenantId())) {
            throw new CustomException("岗位名称已存在");
        }
        if (!this.checkUniquePostCode(req.getPostCode(), req.getId(), req.getTenantId())) {
            throw new CustomException("岗位编码已存在");
        }
        SysPost entity = BeanUtil.copyProperties(req, SysPost.class);
        this.updateById(entity);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void remove(String ids) {
        List<String> idList = Arrays.asList(ids.split(","));
        idList.forEach(item -> {
            SysPost sysPost = this.getById(item);
            SysUserPost sysUserPost = sysUserPostService.getOne(Wrappers.lambdaQuery(SysUserPost.class).eq(SysUserPost::getPostId, item).last("LIMIT 1"));
            if (Objects.nonNull(sysUserPost)) {
                throw new CustomException(String.format("岗位【%s】已被使用，无法删除", sysPost.getPostName()));
            }
        });
        this.removeByIds(Arrays.asList(ids.split(",")));
    }

    @Override
    public SysPost view(String id) {
        return this.getById(id);
    }

    @Override
    public List<SysPost> listOptions() {
        LambdaQueryWrapper<SysPost> queryWrapper = Wrappers.lambdaQuery();
        queryWrapper.eq(SysPost::getStatus, StatusEnum.YES.getCode())
                .eq(SysPost::getTenantId, SecurityUtils.getTenantId())
                .orderByAsc(SysPost::getSort);
        return this.list(queryWrapper);
    }

    @Override
    public List<SysPost> selectOptions(Long tenantId) {
        LambdaQueryWrapper<SysPost> queryWrapper = Wrappers.lambdaQuery();
        queryWrapper.eq(SysPost::getStatus, StatusEnum.YES.getCode())
                .eq(SysPost::getTenantId, tenantId)
                .orderByAsc(SysPost::getSort);
        return this.list(queryWrapper);
    }

    private Boolean checkUniquePostCode(String value, Long id, Long tenantId) {
        if (StrUtil.isBlank(value)) {
            return true;
        }
        id = Objects.isNull(id) ? -1L : id;
        SysPost entity = this.getOne(Wrappers.lambdaQuery(SysPost.class)
                .eq(SysPost::getPostCode, value)
                .eq(SysPost::getTenantId, tenantId));
        return Objects.isNull(entity) || entity.getId().longValue() == id.longValue();
    }

    private Boolean checkUniquePostName(String value, Long id, Long tenantId) {
        if (StrUtil.isBlank(value)) {
            return true;
        }
        id = Objects.isNull(id) ? -1L : id;
        SysPost entity = this.getOne(Wrappers.lambdaQuery(SysPost.class)
                .eq(SysPost::getPostName, value)
                .eq(SysPost::getTenantId, tenantId));
        return Objects.isNull(entity) || entity.getId().longValue() == id.longValue();
    }

}
